home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir39 / borfix.zip / TI1300.C < prev    next >
C/C++ Source or Header  |  1994-08-23  |  6KB  |  240 lines

  1.   /************************************************************
  2.     This program demonstrates the use of EMS (expanded memory.)
  3.     In this program, we use EMS to store a simulated array of
  4.     50,000 long ints.  Compile in any memory model.
  5.     It is not optimized, for purposes of clarity.
  6.     Many thanks to Ray Duncan for his lucid exposition of
  7.     EMS in "Extending DOS"
  8.    ************************************************************/
  9.  
  10.   #include <fcntl.h>
  11.   #include <sys\stat.h>
  12.   #include <io.h>
  13.   #include <stdio.h>
  14.   #include <dos.h>
  15.   #include <stdlib.h>
  16.  
  17.   #define TRUE 1
  18.   #define FALSE 0
  19.   #define EMS_INT 0x67
  20.   #define PAGESIZE 16384
  21.  
  22.   int EMSHandle;
  23.   int pageMap[4] = { -1, -1, -1, -1 };
  24.   int pageFrame;
  25.  
  26.   // Function to test for existence of EMS.  If coding a TSR or
  27.   // ISR, you will be unable to call DOS and therefore must check
  28.   // if the name EMMXXXX0 is at offset 10 from the entrypoint to
  29.   // the EM Manager pointed to by vector 0x67
  30.  
  31.   char EMSExists(void)
  32.   {
  33.        int handle,devInfo,outputStatus;
  34.        // The expanded memory manager if present should show up
  35.        // as a filename
  36.        if ((handle=open("EMMXXXX0",O_RDONLY|O_BINARY)) == -1)
  37.             return FALSE;
  38.        devInfo=ioctl(handle,0);
  39.        // if bit 7 is 0 it is a file
  40.        if ((devInfo & 0x80) == 0)
  41.        {
  42.             printf("Found File EMMXXXX0?!?\n");
  43.  
  44.             close(handle);
  45.             return FALSE;
  46.        }
  47.        outputStatus=ioctl(handle,7);
  48.        if (outputStatus==0)
  49.        {
  50.             printf("EMM present but not responding\n");
  51.             close(handle);
  52.             return FALSE;
  53.        }
  54.        // file handle for EMS manager is useless for anything
  55.        // further, so we'll just close it.
  56.        close(handle);
  57.        return TRUE;
  58.   }
  59.  
  60.   // Assuming EMS is present, it may still not be functional
  61.   // due to a hardware error or who knows what, so we have
  62.   // a function to check whether the expanded memory manager
  63.   // is ready to do its business.
  64.  
  65.   char EMSFunctional(void)
  66.   {
  67.        _AH=0x40;
  68.        geninterrupt(EMS_INT);
  69.        if (_AH==0) return FALSE;
  70.        else return TRUE;
  71.   }
  72.  
  73.   // EMSSize() finds out the total and available pages of EMS
  74.  
  75.   void EMSSize(int *pagesTotal, int *pagesAvail)
  76.   {
  77.       _AH=0x42;
  78.       geninterrupt(0x67);
  79.       *pagesAvail=_BX;
  80.       *pagesTotal=_DX;
  81.   }
  82.  
  83.   // EMSAlloc() tries to allocate the number of pages corresponding
  84.   // to the size in bytes of the allocation requested.
  85.  
  86.   char EMSAlloc(unsigned long bytes)
  87.   {
  88.        int numPages;
  89.        numPages=(int) (bytes/PAGESIZE);
  90.        if (bytes%PAGESIZE != 0) ++numPages;
  91.        _BX=numPages-1;
  92.        _AH=0x43;
  93.        geninterrupt(EMS_INT);
  94.        EMSHandle=_DX;
  95.        if (_AH!=0)
  96.        {
  97.             printf("Allocation of %d pages failed\n",numPages);
  98.             return FALSE;
  99.        }
  100.        else
  101.        {
  102.             printf("Allocated %d pages\n",numPages);
  103.             return TRUE;
  104.        }
  105.   }
  106.  
  107.   // CleanUp() tries to deallocate our EMS allocation
  108.  
  109.   void CleanUp(void)
  110.   {
  111.        _AH=0x45;
  112.        _DX=EMSHandle;
  113.        geninterrupt(EMS_INT);
  114.        if (_AH!=0) printf("Deallocation failed!\n");
  115.   }
  116.  
  117.   void EMSRemap(int logpage)
  118.   {
  119.        // the mapping scheme we're using is that the physical page
  120.        // mapping for a logical page is the logical page mod 4
  121.        printf("Mapping logical page %d\n",logpage);
  122.        // ask to map logical page _BX into physical page (0->3) _AL
  123.        _AL=logpage&3;
  124.        _BX=logpage;
  125.        _DX=EMSHandle;
  126.        _AH=0x44;
  127.        geninterrupt(EMS_INT);
  128.        if (_AH!=0)
  129.        {
  130.             printf("Mapping failed!\n");
  131.             CleanUp();
  132.             exit(1);
  133.        }
  134.        pageMap[logpage&3]=logpage;
  135.   }
  136.  
  137.   // GetEMSPageFrame finds the segment that the page frame lives
  138.   // at and stores it in pageFrame for use by PutVal and GetVal
  139.  
  140.   void GetEMSPageFrame(void)
  141.   {
  142.        _AH=0x41;
  143.        geninterrupt(EMS_INT);
  144.        pageFrame=_BX;
  145.        if (_AH!=0)
  146.        {
  147.             printf("Cannot get page frame!\n");
  148.             CleanUp();
  149.             exit(1);
  150.        }
  151.   }
  152.  
  153.  
  154.   // PutVal() puts a value into the array, asking for a page to be
  155.   // remapped if the correct page isn't in memory.
  156.  
  157.   // With both PutVal() and GetVal(), the code could be optimized
  158.   // considerably by using bitshifts instead of multiplies.  And,
  159.   // a real application would probably be coded to check less
  160.   // often for the page being present.
  161.  
  162.   void PutVal(unsigned long loc, unsigned long val)
  163.   {
  164.        unsigned int logPage; // logical page
  165.        unsigned long far * physLoc;
  166.        // loc*sizeof(long) is the byte address of the item; we
  167.        // divide by PAGESIZE to figure out which logical page
  168.        // it's on
  169.        logPage= (int) (loc*sizeof(long)/PAGESIZE);
  170.        // logical page mod 4 is our scheme to map a logical page
  171.        // to a physical page.   pageMap tells us which logical
  172.        // page is being kept in each physical page.
  173.  
  174.        if (pageMap[logPage&3]!=logPage) EMSRemap(logPage);
  175.        // the offset in the EMS buffer will be sizeof(long) times
  176.        // the array index, mod 64K; the segment of the EMS buffer
  177.        // is of course pageFrame.
  178.        physLoc= (unsigned long far *)
  179.             MK_FP(pageFrame,(loc*sizeof(long))&65535U);
  180.        *physLoc=val;
  181.   }
  182.  
  183.   // GetVal() gets a value from the 'array', asking for a page to
  184.   // be remapped if the correct page isn't in memory.
  185.  
  186.   unsigned long GetVal(unsigned long loc)
  187.   {
  188.        unsigned int logPage;
  189.        unsigned long far * physLoc;
  190.        logPage= (int) (loc*sizeof(long)/PAGESIZE);
  191.        if (pageMap[logPage&3]!=logPage) EMSRemap(logPage);
  192.        physLoc= (unsigned long far *)
  193.             MK_FP(pageFrame,(loc*sizeof(long))&65535U);
  194.        return *physLoc;
  195.   }
  196.  
  197.   int main(void)
  198.   {
  199.        int pagesAvail,pagesTotal;
  200.        unsigned long i;
  201.        if (EMSExists()) printf("Found EMS\n");
  202.        else
  203.        {
  204.             printf("No EMS");
  205.             return(1);
  206.        }
  207.        if (EMSFunctional) printf("EMS Working\n");
  208.        else
  209.        {
  210.             printf("EMS present but malfunctioning\n");
  211.             return(1);
  212.        }
  213.        EMSSize(&pagesTotal,&pagesAvail);
  214.        printf("EMS Pages -- Total: %u, Available %u (%uK)\n",
  215.                  pagesTotal,pagesAvail,pagesAvail*16);
  216.  
  217.        // allocate enough space in EMS for 50,000 long ints
  218.        if (!EMSAlloc(sizeof(long)*50000L))
  219.             return(1);
  220.  
  221.        GetEMSPageFrame();
  222.        printf("Page frame at segment 0x%4X\n",pageFrame);
  223.  
  224.        // Test our EMS functions by storing and retrieving
  225.        // 50,000 long ints
  226.        for (i=0; i<50000L; ++i)
  227.             PutVal(i,i);
  228.        for (i=0; i<50000L; ++i)
  229.             if (GetVal(i)!=i)
  230.             {
  231.                  printf("%d != %d\n",GetVal(i),i);
  232.                  break;
  233.             }
  234.  
  235.        CleanUp();
  236.        return(0);
  237.   }
  238.  
  239.  
  240.